iT邦幫忙

2021 iThome 鐵人賽

DAY 15
0
AI & Data

手寫中文字之影像辨識系列 第 15

【第15天】訓練模型-ResNet152V2

  • 分享至 

  • xImage
  •  

摘要

  1. ResNet152V2

    1.1 來源
    1.2 架構
    1.3 特性

  2. 訓練過程

    2.1 預訓練模型
    2.2 設置Callbacks
    2.3 設置訓練集
    2.4 開始訓練模型
    2.5 儲存模型與紀錄學習曲線

  3. 模型訓練結果

    3.1 學習曲線
    3.2 Accuracy與Loss

  4. 驗證模型準確度

    4.1 程式碼
    4.2 驗證結果


內容

  1. ResNet152V2

    1.1 來源:

    • 簡介:網路結構的深度,與影像識別效果關係密切。然而隨著網路加到極深,模型準確度卻提升有限。故ResNet引入residual learning的概念,嘗試解決訓練過程中梯度彌散的現象。
      ※ 註:梯度彌散的詳細解釋可參考此處
    • 時程:於2015年提出深度殘差網路概念,並於2016年發表論文,同年收錄在CVPR。
    • 論文名稱:Deep Residual Learning for Image Recognition

    1.2 架構

    • Resnet34:Residual Block

      • 啟發:比較34層卷積網路(VGG19)與34層殘差網路。

      ※ 註:詳細架構圖請參考論文Page4 Figure3

      • Residual Block
    • ResNet50/101/152:Bottleneck Block

      • 參照Inception module的概念,將3 * 3卷積拆分成兩個1 * 1與一個3 * 3卷積,減少模型參數量。後續在增加模型深度的同時,不會增加過多的運算量。

      • Inception module

      • ResNet50/101/152

    1.3 特性

    • ResNet的殘差直連通路,在訓練過程中不容易梯度彌散,使極深層的網路結構更容易收斂。

    • 模型穩定性佳,可透過堆疊的方式加深網路,論文中作者探索在1000層以下,影像識別效果會隨著網路加深,提升模型表現。而超過1000層(1202層),可能訓練效率低下或發生Overfitting情況,降低模型效能。

      ※ 詳細請參考論文Page8 Exploring Over 1000 layers

    • 觀察VGG NET與達到Residual Net在ImageNet上的表現,Residual Net優於VGG Net,且複雜度明顯低於VGG Net。

  2. 訓練過程:

    2.1 預訓練模型

    # IMPORT MODULES
    from keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau
    from keras.layers import Input, Dense, GlobalAveragePooling2D
    from keras.preprocessing.image import ImageDataGenerator
    from keras.optimizers import Adam
    import matplotlib.pyplot as plt
    from keras.models import Model
    from keras.applications import ResNet152V2
    
    # -----------------------------1.客製化模型--------------------------------
    # 載入keras模型(更換輸出圖片尺寸)
    model = ResNet152V2(include_top=False,
                     weights='imagenet',
                     input_tensor=Input(shape=(80, 80, 3))
                     )
    
    # 定義輸出層
    x = model.output
    x = GlobalAveragePooling2D()(x)
    predictions = Dense(800, activation='softmax')(x)
    model = Model(inputs=model.input, outputs=predictions)
    
    # 編譯模型
    model.compile(optimizer=Adam(lr=0.001),
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    

    2.2 設置Callbacks

    # ---------------------------2.設置callbacks----------------------------
    # 設定earlystop條件
    estop = EarlyStopping(monitor='val_loss', patience=10, mode='min', verbose=1)
    
    # 設定模型儲存條件
    checkpoint = ModelCheckpoint('ResNet152V2_checkpoint_v1.h5', verbose=1,
                              monitor='val_loss', save_best_only=True,
                              mode='min')
    
    # 設定lr降低條件(0.001 → 0.0002 → 0.00004 → 0.00001)
    reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2,
                               patience=5, mode='min', verbose=1,
                               min_lr=1e-5)
    

    2.3 設置訓練集

    # -----------------------------3.設置資料集--------------------------------
    # 設定ImageDataGenerator參數(路徑、批量、圖片尺寸)
    train_dir = './workout/train/'
    valid_dir = './workout/val/'
    test_dir = './workout/test/'
    batch_size = 64
    target_size = (80, 80)
    
    # 設定批量生成器
    train_datagen = ImageDataGenerator(rescale=1./255, 
                                       rotation_range=20,
                                       width_shift_range=0.2,
                                       height_shift_range=0.2,
                                       shear_range=0.2, 
                                       zoom_range=0.5,
                                       fill_mode="nearest")
    
    val_datagen = ImageDataGenerator(rescale=1./255)
    
    test_datagen = ImageDataGenerator(rescale=1./255)
    
    # 讀取資料集+批量生成器,產生每epoch訓練樣本
    train_generator = train_datagen.flow_from_directory(train_dir,
                                          target_size=target_size,
                                          batch_size=batch_size)
    
    valid_generator = val_datagen.flow_from_directory(valid_dir,
                                          target_size=target_size,
                                          batch_size=batch_size)
    
    test_generator = test_datagen.flow_from_directory(test_dir,
                                          target_size=target_size,
                                          batch_size=batch_size,
                                          shuffle=False)
    

    2.4 重新訓練模型權重

    # -----------------------------4.開始訓練模型------------------------------
    # 重新訓練權重
    history = model.fit_generator(train_generator,
                       epochs=50, verbose=1,
                       steps_per_epoch=train_generator.samples//batch_size,
                       validation_data=valid_generator,
                       validation_steps=valid_generator.samples//batch_size,
                       callbacks=[checkpoint, estop, reduce_lr])
    

    2.5 儲存模型與紀錄學習曲線

    # -----------------------5.儲存模型、紀錄學習曲線------------------------
    # 儲存模型
    model.save('./ResNet152V2_retrained_v1.h5')
    print('已儲存ResNet152V2_retrained_v1.h5')
    
    # 畫出acc學習曲線
    acc = history.history['accuracy']
    epochs = range(1, len(acc) + 1)
    val_acc = history.history['val_accuracy']
    plt.plot(epochs, acc, 'bo', label='Training acc')
    plt.plot(epochs, val_acc, 'r', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend(loc='lower right')
    plt.grid()
    # 儲存acc學習曲線
    plt.savefig('./acc.png')
    plt.show()
    
    # 畫出loss學習曲線
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    plt.plot(epochs, loss, 'bo', label='Training loss')
    plt.plot(epochs, val_loss, 'r', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend(loc='upper right')
    plt.grid()
    # 儲存loss學習曲線
    plt.savefig('loss.png')
    plt.show()
    
  3. 模型訓練結果

    3.1 訓練epochs:31 epochs。

    3.2 耗費時間:4小時17分32秒(15452秒)。

    3.3 學習曲線

    3.4 Accuary與Loss

  4. 驗證準確度

    4.1 程式碼

    # -------------------------6.驗證模型準確度--------------------------
    # 以vali資料夾驗證模型準確度
    test_loss, test_acc = model.evaluate_generator(test_generator,
                                steps=test_generator.samples//batch_size,
                                verbose=1)
    print('test acc:', test_acc)
    print('test loss:', test_loss)
    

    4.2 驗證結果


小結

  1. ResNet為深度學習帶來新的啟發,現在許多主流模型都採Residual learning概念。
  2. 下一章目標是:介紹第三個預訓練模型DenseNet201,與分享訓練成果」。

讓我們繼續看下去...


參考資料

  1. Deep Residual Learning for Image Recognition
  2. Residual Leaning: 認識ResNet與他的冠名後繼者ResNeXt、ResNeSt
  3. Identity Mappings in Deep Residual Networks
  4. [論文] Deep Residual Learning for Image Recognition
  5. 梯度彌散與梯度爆炸

上一篇
【第14天】訓練模型-Xception
下一篇
【第16天】訓練模型-DenseNet201
系列文
手寫中文字之影像辨識31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言